package service

import (
	"gobase/app/model"
	"gobase/util"
	"strconv"

	"github.com/casbin/casbin"

	"github.com/Sirupsen/logrus"
	"github.com/gin-gonic/gin"
	"github.com/pkg/errors"
	"github.com/xormplus/xorm"
)

type RoleService struct {
	dao *xorm.Engine
	log *logrus.Logger
	ce  *casbin.Enforcer
}

//初始化方法
func NewRoleService(c *gin.Context) *RoleService {
	return &RoleService{dao: util.GetDb(c), log: util.GetLog(c), ce: util.GetCasbin(c)}
}

//角色列表
func (srv *RoleService) QueryList(p *util.Page, rolename string) (*util.Page, []*model.Role) {
	db := srv.dao
	var resultp *util.Page = util.NewPage(p)
	var roleList []*model.Role
	var sql = "select ### from role as t "
	var wheres = []util.SqlWhere{}

	if rolename != "" {
		wheres = append(wheres, util.NewSqlWhere("t.rolename", rolename+"%", "like", false))
	}
	countSQL, listSQL, args := util.GenSql(sql, "t.*", wheres)

	//查询总数
	total, err := db.SQL(countSQL, args...).Count(new(model.Role))
	if err != nil {
		srv.log.Errorf("RoleService->QueryList 列表查询错误：%s", err)
		return resultp, roleList
	}

	//计算分页
	resultp.SetCount(int(total), resultp.GetPageSize())
	//查询列表
	err = db.SQL(listSQL, args...).Desc("t.id").Limit(resultp.GetPageParam()).Find(&roleList)
	if err != nil {
		srv.log.Errorf("RoleService->QueryList 列表查询错误：%s", err)
	}

	return resultp, roleList
}

//新增角色
func (srv *RoleService) Add(role *model.Role) error {
	//判断角色名是否被使用
	exist := srv.IsExist(role.Rolename, 0)
	if exist {
		return errors.New("[" + role.Rolename + "]角色名已被使用!")
	} else {
		_, err := srv.dao.Insert(role)
		if err != nil {
			return errors.Wrap(err, "新增角色失败!")
		}
	}
	return nil
}

//更新角色信息
func (srv *RoleService) Update(id int, role *model.Role) error {
	//判断角色名是否被使用
	exist := srv.IsExist(role.Rolename, id)
	if exist {
		return errors.New("[" + role.Rolename + "]角色名已被使用!")
	} else {
		_, err := srv.dao.Id(id).Cols("role,state").Update(role)
		if err != nil {
			return errors.Wrap(err, "更新角色信息失败!")
		}
	}
	return nil
}

//删除角色信息
func (srv *RoleService) DeleteById(id int) error {
	session := srv.dao.NewSession()
	defer session.Close()

	if err := session.Begin(); err != nil {
		return errors.Wrap(err, "开启事务失败!")
	}

	_, err1 := session.SQL("delete from role_user where roleid=?", id).Execute()
	if err1 != nil {
		return errors.Wrap(err1, "删除角色关联用户失败!")
	}
	_, err2 := session.SQL("delete from role_resource where roleid=?", id).Execute()
	if err2 != nil {
		return errors.Wrap(err2, "删除角色关联权限失败!")
	}
	_, err3 := session.Id(id).Delete(new(model.Role))
	if err3 != nil {
		return errors.Wrap(err3, "删除角色失败!")
	}

	err := session.Commit()
	if err != nil {
		return errors.Wrap(err, "提交事务失败!")
	}
	srv.ce.DeleteRole(strconv.Itoa(id))
	return nil
}

//根据ID查询一条记录
func (srv *RoleService) GetByID(id int) (model.Role, error) {
	var role model.Role
	_, err := srv.dao.Sql("select * from role t where t.id=?", id).Get(&role)

	if err != nil {
		return role, errors.Wrap(err, "获取角色信息失败！")
	}
	return role, nil
}

//判断角色名是否被使用
func (srv *RoleService) IsExist(rolename string, id int) bool {
	var exist bool
	var err error
	sql := "select * from role t where t.rolename=? "
	if id > 0 {
		sql = sql + " and t.id<>? "
		exist, err = srv.dao.SQL(sql, rolename, id).Exist()
	} else {
		exist, err = srv.dao.SQL(sql, rolename).Exist()
	}

	if err != nil {
		srv.log.Errorf("RoleService->IsExist 判断角色名是否存在错误：%s", err)
	}
	return exist
}

//启用/禁用
func (srv *RoleService) EnableOrDisable(id int, state string) error {
	updateSQL := "update role set state=? where id=? "
	_, err := srv.dao.Sql(updateSQL, state, id).Execute()
	if err != nil {
		return errors.Wrap(err, "更新角色状态失败!")
	}
	return nil
}
